/**
 * @TODO Make sure JSON exists... Or do something else?
 *
 * var config = {
 *		debug: false,
 *		autoReconnect: true,
 *		onopen: function() {console.log('connection open');},
 *		onclose: function() {console.log('connection closed');},
 *		onmessage: function(message) {console.log('message received', message);},
 *		onsubscribe: function(channel) {console.log('subscribed to', channel);},
 *		onunsubscribe: function() {console.log('unsubscribed from', channel);},
 *	};
 * usage:
 * TrophyWebsocket.connect('my-app-id', config).subscribe('my-channel', function(data) {});
 */
(function(window) {
	function tws() {
		var _config = {};
		var _self = this;
//		var _wsurl = "ws://localhost:3050/{0}";
		// var _wsProto = 'ws:';
		// if (window.document.location.protocol == 'https:') _wsProto = 'wss:';
		// var _wsurl = _wsProto + '//' + window.document.location.host + '/{0}';
		var _wsurl = 'wss://push.pro11.com/{0}';
		var _appid;
		var _ws;
		var _connected = false;
		var _manualClose = false;
		var _channels = {};
		this.connect = function(appid, config) {
			_appid = appid;
			_config = _setConfig(config);
			_open();
			
			return _self;
		};
		
		this.subscribe = function(channel, callback) {
			_channels[channel] = callback;
			if (_connected) 
				_subscribe(channel);
			return _self;
		};

		this.unsubscribe = function(channel) {
			delete(_channels[channel]);
			if (_connected) 
				_unsubscribe(channel);
			return _self;
		};
		
		this.close = function() {
			_manualClose = true;
			_channels = {};
			_ws.close();
		};

		function _subscribe(channel) {
			if(!channel || !_ws) return;
			var d = {
				subscribe: channel,
			};
			_ws.send(JSON.stringify(d));
		}

		function _unsubscribe(channel) {
			if(!channel || !_ws) return;
			var d = {
				unsubscribe: channel,
			};
			_ws.send(JSON.stringify(d));
		}

		function _open() {
			log("open");
			_ws = new WebSocket(_format(_wsurl,_appid));
			_ws.onopen = function(socket) {
				log("open", socket);
				_connected = true;
				_manualClose = false;
				for (var i in _channels) {
					_subscribe(i, _channels[i]);					
				}
				if (_config.onopen)
					_config.onopen();
			};

			_ws.onclose = function(socket) {
				log("close", socket);
				_connected = false;
				if (!_manualClose && _config.autoReconnect)
					setTimeout(_open, 1000);

				if (_config.onclose)
					_config.onclose();
			};

			_ws.onerror = function() {
				log("on error");
				if (_config.autoReconnect)
					setTimeout(_open, 1000);

				if (_config.onerror)
					_config.onerror();
			};

			_ws.onmessage = function(message) {
				log("message", message.data);
				var data = JSON.parse(message.data);
				log('data', data);
				if (data.subscribed) {
					if (_config.onsubscribe)
						_config.onsubscribe(data.subscribed);
				} else if (data.unsubscribed) {
					if (_config.onunsubscribe)
						_config.onunsubscribe(data.unsubscribed);
				} else {
					var message = data.message;
					// try {
					// 	message = JSON.parse(data.message);
					// } catch(e) {}
					if (_config.onmessage)
						_config.onmessage(message, data.channel);
					if (_channels[data.channel])
						_channels[data.channel](message);

				}
			};
		}

		function log() {
			if (_config.debug)
				console.log.apply(this, arguments);
		}

		function _setConfig(config) {
			config = config || {};
			var def = {
				debug: false,
				autoReconnect: true,
				onopen: null,
				onclose: null,
				onmessage: null,
				onsubscribe: null,
				onunsubscribe: null,
			};
			for (var i in def) {
				if ((typeof config[i]) == 'undefined') {
					config[i] = def[i];
				}
			}
			return config;
		}
		function _format(format) {
		    var args = Array.prototype.slice.call(arguments, 1);
		    return format.replace(/{(\d+)}/g, function(match, number) { 
	      		return typeof args[number] != 'undefined'
				   ? args[number] 
				   : match
				;
			});
		};
		return _self;
	}
	window.TrophyWebsocket = new tws();
})(window);
